home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #1 / Amiga Plus 1995 #1.iso / fish-disketten / fish_941-950 / d946 / priman / priman.c < prev    next >
C/C++ Source or Header  |  1994-12-13  |  71KB  |  1,830 lines

  1. /*
  2.  
  3.     Task Priority Manager
  4.     Copyright 1993 Barry McConnell
  5.     bmccnnll@unix1.tcd.ie
  6.  
  7. */
  8.  
  9. #include <exec/types.h>
  10. #include <exec/execbase.h>
  11. #include <exec/memory.h>
  12. #include <dos/dos.h>
  13. #include <dos/dosextens.h>
  14. #include <intuition/intuition.h>
  15. #include <intuition/intuitionbase.h>
  16. #include <intuition/gadgetclass.h>
  17. #include <intuition/screens.h>
  18. #include <graphics/gfxbase.h>
  19. #include <graphics/text.h> 
  20. #include <libraries/asl.h>
  21. #include <libraries/gadtools.h>
  22. #include <libraries/commodities.h>
  23. #include <workbench/startup.h>
  24. #include <workbench/workbench.h>
  25. #include <workbench/icon.h>
  26.  
  27. #include <stdio.h>
  28. #include <string.h>
  29.  
  30. #include <proto/dos.h>
  31. #include <proto/exec.h>
  32. #include <proto/intuition.h>
  33. #include <proto/graphics.h>
  34. #include <proto/gadtools.h>
  35. #include <proto/diskfont.h>
  36. #include <proto/asl.h>
  37. #include <proto/icon.h>
  38. #include <proto/commodities.h>
  39. #include <proto/wb.h>
  40. #include <clib/alib_protos.h>
  41.  
  42. #define WINDOWIDCMP     IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_NEWSIZE | BUTTONIDCMP | LISTVIEWIDCMP | RAWKEY
  43. #define MaxTasks        256  /* talk about a very loaded system... */
  44. #define MaxHotkey       20
  45. #define ScrollBarWidth  16
  46.  
  47. #define LISTGAD         1
  48. #define SLIDERGAD       2
  49. #define BREAKGAD        3
  50. #define KILLGAD         4
  51. #define SETTINGSGAD     5
  52. #define GFONTGAD        6
  53. #define LFONTGAD        7
  54. #define GBOXGAD         8
  55. #define LBOXGAD         9
  56. #define CONFIRMGAD      10
  57. #define ICONIFYGAD      11
  58. #define SAVEGAD         12
  59. #define USEGAD          13
  60. #define CANCELGAD       14
  61. #define COMGAD          15
  62. #define POPUPGAD        16
  63. #define HOTKEYGAD       17
  64. #define PRIORITYGAD     18
  65.  
  66. #define OPEN_MAIN       1
  67. #define CLOSE_MAIN      2
  68. #define REDRAW_MAIN     3
  69. #define UPDATE          4
  70. #define OPEN_SETTINGS   5
  71. #define CLOSE_SETTINGS  6
  72. #define NEW_FONT        7
  73. #define QUIT            8
  74.  
  75. #define LOCK_ERROR      100
  76. #define VISINFO_ERROR   101
  77. #define FONT_ERROR      102
  78. #define GADGET_ERROR    103
  79. #define MAIN_ERROR      104
  80. #define TASK_ERROR      105
  81. #define SETTINGS_ERROR  106
  82. #define CX_ERROR        107
  83.  
  84. #define ALL_OKAY        200
  85.  
  86. void __regargs __chkabort(void) {}  /* turn off SAS/C v6 CTRL-C checking */
  87.  
  88. struct listType  /* standard Node type with extra space to store the original task structure, so we can find it again */
  89.     {
  90.     struct Node mainNode;
  91.     struct Task *mainTask;
  92.     };
  93.  
  94. extern struct ExecBase  *SysBase;
  95. static UBYTE            *version = "$VER: PriMan 1.1 (29.09.93)";
  96. int                     error = 0;  /* for passing an error or command between procedures */
  97. UWORD                   osver = 0;  /* Kickstart version */
  98.  
  99. struct EasyStruct about =  /* And the user thought he was getting full online help... */
  100.     {
  101.     sizeof(struct EasyStruct),
  102.     0,
  103.     "About PriMan",
  104.     "Task Priority Manager v1.1\nFreely Distributable\nCopyright 1993 Barry McConnell\nbmccnnll@unix1.tcd.ie",
  105.     "Okay"
  106.     };
  107.  
  108. struct EasyStruct badFilter =
  109.     {
  110.     sizeof(struct EasyStruct),
  111.     0,
  112.     "PriMan warning",
  113.     "Invalid hotkey -- suggest you change it",
  114.     "Okay"
  115.     };
  116.  
  117. UWORD __chip waitPointer[] =
  118.     {
  119.     0x0000, 0x0000,
  120.     0x0400, 0x07c0,
  121.     0x0000, 0x07c0,
  122.     0x0100, 0x0380,
  123.     0x0000, 0x07e0,
  124.     0x07c0, 0x1ff8,
  125.     0x1ff0, 0x3fec,
  126.     0x3ff8, 0x7fde,
  127.     0x3ff8, 0x7fbe,
  128.     0x7ffc, 0xff7f,
  129.     0x7efc, 0xffff,
  130.     0x7ffc, 0xffff,
  131.     0x3ff8, 0x7ffe,
  132.     0x3ff8, 0x7ffe,
  133.     0x1ff0, 0x3ffc,
  134.     0x07c0, 0x1ff8,
  135.     0x0000, 0x07e0,
  136.     0x0000, 0x0000,
  137.     };
  138.  
  139.  
  140. /*
  141.     Display a busy pointer in the current window, and prevent user from clicking on any gadgets.
  142. */
  143.  
  144. void busyPointer(struct Window *mainWindow, struct Window *setWindow, struct Requester *req1, struct Requester *req2)
  145. {
  146. mainWindow -> UserData = (BYTE *)(mainWindow -> MinWidth << 16 | mainWindow -> MinHeight);  /* sneaky!! */
  147. WindowLimits(mainWindow, mainWindow -> Width, mainWindow -> Height, mainWindow -> Width, mainWindow -> Height);
  148.  
  149. InitRequester(req1);
  150. Request(req1, mainWindow);
  151. if (osver < 39)
  152.     SetPointer(mainWindow, waitPointer, 16, 16, -6, 0);
  153. else
  154.     SetWindowPointer(mainWindow,    WA_BusyPointer,     TRUE,
  155.                                     WA_PointerDelay,    TRUE,
  156.                                     TAG_END);
  157.  
  158. if (setWindow)
  159.     {
  160.     InitRequester(req2);
  161.     Request(req2, setWindow);
  162.     if (osver < 39)
  163.         SetPointer(setWindow, waitPointer, 16, 16, -6, 0);
  164.     else
  165.         SetWindowPointer(setWindow, WA_BusyPointer,     TRUE,
  166.                                     WA_PointerDelay,    TRUE,
  167.                                     TAG_END);
  168.     }
  169. }
  170.  
  171.  
  172. /*
  173.     Restore the pointer to normal.
  174. */
  175.  
  176. void normalPointer(struct Window *mainWindow, struct Window *setWindow, struct Requester *req1, struct Requester *req2)
  177. {
  178. ClearPointer(mainWindow);
  179. EndRequest(req1, mainWindow);
  180. WindowLimits(mainWindow, (LONG)(mainWindow -> UserData) >> 16, (LONG)(mainWindow -> UserData) & 0xffff, ~0, ~0);  /* restore limits */
  181.  
  182. if (setWindow)
  183.     {
  184.     ClearPointer(setWindow);
  185.     EndRequest(req2, setWindow);
  186.     }
  187. }
  188.  
  189.  
  190. /*
  191.     Join a task name and its priority together. Extra spaces are placed between the
  192.     two components to make the string an exact length. If the task has an appropriate
  193.     CLI number, that will be added in before its name. The task name will be truncated
  194.     if there is not enough room to fit it (and its name) in length. There must be
  195.     length+1 bytes free in dest, because of the \0 char.
  196. */
  197.  
  198. void createString(struct Task *task, char *dest, int length)
  199. {
  200. int numLen, cli, i = 0, j = 0;
  201. char digits[5], clitext[11];
  202. char *name;
  203. APTR bstr;
  204. BYTE maxlen = -1;  /* normally won't be used */
  205.  
  206. numLen = sprintf(digits, "%d", task -> tc_Node.ln_Pri);  /* saves me writing an integer -> ASCII routine */
  207.  
  208. if (((task -> tc_Node.ln_Type) == NT_PROCESS) && (cli = ((struct Process *)task) -> pr_TaskNum))  /* is it a process with a CLI attached? */
  209.     {
  210.     sprintf(clitext, "CLI #%d: ", cli);
  211.     for (; (i < length - numLen - 1) && clitext[i]; i++)  /* might have to disard some of the characters */
  212.         dest[i] = clitext[i];
  213.     bstr = BADDR(((struct CommandLineInterface *)(BADDR(((struct Process *)task) -> pr_CLI))) -> cli_CommandName);
  214.     name = (char *)(bstr)+1;
  215.     maxlen = *((BYTE *)bstr);
  216.     }
  217.     else
  218.         name = task -> tc_Node.ln_Name;
  219.  
  220. for (; (i < length - numLen - 1) && name[j] && maxlen; i++, j++, maxlen--)
  221.     dest[i] = name[j];
  222.  
  223. do
  224.     dest[i++] = ' ';
  225. while (i < length - numLen);
  226.  
  227. j = 0;
  228. do
  229.     dest[i++] = digits[j];
  230. while (digits[j++]);
  231. }
  232.  
  233.  
  234. /*
  235.     Join together a font name up to the ".", and its size.
  236. */
  237.  
  238. void fontString(struct TextAttr *font, char *dest)
  239. {
  240. int i = 0;
  241.  
  242. while (!((font -> ta_Name)[i] == '.'))
  243.     *(dest++) = (font -> ta_Name)[i++];
  244. sprintf(dest, " %d", font -> ta_YSize);
  245. }
  246.  
  247.  
  248. /*
  249.     Compare two strings. Like "strcmp" but case-insensitive.
  250. */
  251.  
  252. int Compare(char *s, char *t)
  253. {
  254. for (; ((*s & ~32) == (*t & ~32)) && *s; s++, t++)  /* sorry, K&R ;-) */
  255.     ;
  256. return (*s & ~32) - (*t & ~32);
  257. }
  258.  
  259.  
  260. /*
  261.     Safely close a window that might have a shared IDCMP.
  262. */
  263.  
  264. void CloseWindowSafely(struct Window *window)
  265. {
  266. struct IntuiMessage *msg;
  267. struct Node         *succ;
  268.  
  269. Forbid();  /* keep out of race conditions with Intuition */
  270. msg = (struct IntuiMessage *)window -> UserPort -> mp_MsgList.lh_Head;  /* going to look at waiting messages for this window */
  271. while (succ = msg -> ExecMessage.mn_Node.ln_Succ)
  272.     {
  273.     if (msg -> IDCMPWindow == window)  /* referring to us? */
  274.         {
  275.         Remove((struct Node *)msg);
  276.         ReplyMsg((struct Message *)msg);
  277.         }
  278.     msg = (struct IntuiMessage *)succ;  /* we aren't relying on a freed pointer */
  279.     }
  280. window -> UserPort = NULL;  /* to stop Intuition freeing it */
  281. ModifyIDCMP(window, NULL);  /* we don't want any more messages here */
  282. Permit();
  283. CloseWindow(window);
  284. }
  285.  
  286.  
  287. /*
  288.     Close a window (if it's open) and free up its gadget list.
  289. */
  290.  
  291. void FreeWindow(struct Window **window, struct Gadget *glist)
  292. {
  293. if (*window)
  294.     {
  295.     CloseWindowSafely(*window);
  296.     FreeGadgets(glist);
  297.     *window = NULL;
  298.     }
  299. }
  300.  
  301.  
  302. /*
  303.     Remember the co-ordinates of the main window before closing it.
  304. */
  305.  
  306. void GetPos(struct Window *window, WORD *winLeft, WORD *winTop, WORD *winWidth, WORD *winHeight)
  307. {
  308. if (window)
  309.     {
  310.     *winLeft = window -> LeftEdge;
  311.     *winTop = window -> TopEdge;
  312.     *winWidth = window -> Width;
  313.     *winHeight = window -> Height;
  314.     }
  315. }
  316.  
  317.  
  318. /*
  319.     Perform all the necessary stuff before opening any windows.
  320. */
  321.  
  322.  
  323. void setup(struct TextFont **propFont, struct TextFont **monoFont,
  324.             struct TextAttr *propName, struct TextAttr *monoName,
  325.             struct Screen **myScreen, void **visInfo,
  326.             WORD *height, WORD *sysWidth, WORD *sysHeight)
  327. {
  328. struct TextExtent fontSize;
  329.  
  330. if ((*myScreen) = LockPubScreen(NULL))
  331.     {
  332.     if ((*visInfo) = GetVisualInfo(*myScreen, TAG_END))
  333.         {
  334.         if (!propName -> ta_YSize || propName -> ta_Name[0] == ' ')  /* invalid font structure */
  335.             {
  336.             propName -> ta_YSize = (*myScreen) -> Font -> ta_YSize;
  337.             strcpy(propName -> ta_Name, (*myScreen) -> Font -> ta_Name);
  338.             }
  339.  
  340.         if (!monoName -> ta_YSize || monoName -> ta_Name[0] == ' ')
  341.             {
  342.             monoName -> ta_YSize = GfxBase -> DefaultFont -> tf_YSize;
  343.             strcpy(monoName -> ta_Name, GfxBase -> DefaultFont -> tf_Message.mn_Node.ln_Name);
  344.             }
  345.  
  346.         if ((*propFont = OpenDiskFont(propName)) && (*monoFont = OpenDiskFont(monoName)))
  347.             {
  348.             FontExtent(*propFont, &fontSize);  /* figure out pixel size of fonts */
  349.             *height = fontSize.te_Height;
  350.             FontExtent(*monoFont, &fontSize);
  351.             *sysHeight = fontSize.te_Height;
  352.             *sysWidth = fontSize.te_Width;
  353.             }
  354.         else
  355.             {
  356.             error = FONT_ERROR;
  357.             FreeVisualInfo(*visInfo);
  358.             UnlockPubScreen(NULL, *myScreen);
  359.             if (*propFont)  /* and it was monoFont that failed to open */
  360.                 CloseFont(*propFont);
  361.             }
  362.         }
  363.     else
  364.         {
  365.         error = VISINFO_ERROR;
  366.         UnlockPubScreen(NULL, *myScreen);
  367.         }
  368.     }
  369. else
  370.     error = LOCK_ERROR;
  371. }
  372.  
  373.  
  374. /*
  375.     Free any resources used by setup()
  376. */
  377.  
  378. void free(struct TextFont **propFont, struct TextFont *monoFont, void *visInfo, struct Screen *myScreen)
  379. {
  380. if (*propFont)
  381.     {
  382.     CloseFont(*propFont);
  383.     CloseFont(monoFont);
  384.     FreeVisualInfo(visInfo);
  385.     UnlockPubScreen(NULL, myScreen);
  386.     *propFont = NULL;
  387.     }
  388. }
  389.  
  390.  
  391. /*
  392.     Set up the Commodity interface
  393. */
  394.  
  395. void setupCommodity(char *hotkey, struct MsgPort *port, struct Window *mainWindow, struct Window *setWindow,
  396.                     struct NewBroker *newBroker, CxObj **broker, CxObj **filter, CxObj **sender, CxObj **translate)
  397. {
  398. LONG brokerError;
  399.  
  400. if (*broker = CxBroker(newBroker, &brokerError))
  401.     {
  402.     if (*filter = CxFilter(hotkey))
  403.         {
  404.         AttachCxObj(*broker, *filter);
  405.         if (*sender = CxSender(port, 1))
  406.             {
  407.             AttachCxObj(*filter, *sender);
  408.             if (*translate = CxTranslate(NULL))
  409.                 {
  410.                 AttachCxObj(*filter, *translate);
  411.                 ActivateCxObj(*broker, 1);
  412.                 if (CxObjError(*filter) == COERR_BADFILTER)
  413.                     EasyRequest(NULL, &badFilter, NULL, NULL);
  414.                 }
  415.             else
  416.                 error = CX_ERROR;
  417.             }
  418.         else
  419.             error = CX_ERROR;
  420.         }
  421.     else
  422.         error = CX_ERROR;
  423.     }
  424. else
  425.     error = brokerError == CBERR_DUP ? ALL_OKAY : CX_ERROR;  /* already running? */
  426. }
  427.  
  428.  
  429. /*
  430.     Layout the gadgets for the main window, and open it.
  431. */
  432.  
  433. void openMainWindow(struct Window **mainWindow, struct Screen *myScreen, struct Gadget **mainGads,
  434.                     struct Gadget **listGad, struct Gadget **sliderGad,
  435.                     struct Gadget **breakGad, struct Gadget **killGad,
  436.                     struct TextFont *propFont, struct TextAttr *propName, struct TextAttr *monoName,
  437.                     struct MsgPort *port, void *visInfo, int height, int sysHeight, int sysWidth, int *taskLength,
  438.                     WORD *windowTop, WORD winLeft, WORD winTop, WORD *winWidth, WORD *winHeight)
  439.                     
  440. {
  441. struct RastPort     myRast;
  442. WORD                buttonText, listWidth, buttonWidth, minWidth, minHeight;
  443. struct NewGadget    myGad;
  444. struct Gadget       *prevGad;
  445. struct Image        blank = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  446.  
  447. InitRastPort(&myRast);  /* dummy RastPort for getting string lengths */
  448. myRast.Font = propFont;
  449.  
  450. buttonText  = TextLength(&myRast, "Settings...", 11) + INTERWIDTH * 2;
  451.  
  452. *windowTop  = (myScreen -> WBorTop) + myScreen -> Font -> ta_YSize + 1 + INTERHEIGHT;
  453. listWidth   = sysWidth * 7 + ScrollBarWidth + INTERWIDTH * 3 + (osver < 39 ? 4 : 0);  /* full width of a small window (a bug in 2.x clips 4 pixels too early) */
  454. buttonWidth = buttonText * 3 + INTERWIDTH * 4;  /* width of buttons and spacing */
  455. minWidth    = buttonWidth > listWidth ? buttonWidth : listWidth;  /* choose between them */
  456. minHeight   = *windowTop + sysHeight * (osver < 39 ? 5 : 3) + height + INTERHEIGHT * 8 + 2;  /* small ListView (1 or 2 elements) */
  457.  
  458. if (*winWidth < minWidth)  /* so, which is it to be? */
  459.     *winWidth = minWidth;
  460. if (*winWidth > myScreen -> Width)
  461.     *winWidth = myScreen -> Width;
  462. if (*winHeight < minHeight)
  463.     *winHeight = minHeight;
  464. if (*winHeight > myScreen -> Height)
  465.     *winHeight = myScreen -> Height;
  466.  
  467. *taskLength = (*winWidth - ScrollBarWidth - INTERWIDTH * 3 - (osver < 39 ? 4 : 0)) / sysWidth;
  468.  
  469. *mainGads   = NULL;  /* begin laying out gadgets for main window */
  470. prevGad     = CreateContext(mainGads);
  471.  
  472. myGad.ng_LeftEdge   = INTERWIDTH;
  473. myGad.ng_TopEdge    = *windowTop;
  474. myGad.ng_Width      = *winWidth - INTERWIDTH * 2;
  475. myGad.ng_Height     = *winHeight - *windowTop - sysHeight - height - INTERHEIGHT * 7 - 2;
  476. myGad.ng_GadgetText = NULL;
  477. myGad.ng_TextAttr   = monoName;
  478. myGad.ng_GadgetID   = LISTGAD;
  479. myGad.ng_Flags      = NULL;
  480. myGad.ng_VisualInfo = visInfo;
  481.  
  482. prevGad = *listGad = CreateGadget(LISTVIEW_KIND, prevGad, &myGad,
  483.                                     GTLV_Labels,            NULL,
  484.                                     GTLV_ShowSelected,      NULL,
  485.                                     TAG_END);
  486.  
  487. if (!(*mainWindow || osver < 39))  /* if possible, silently adjust its height for perfect spacing */
  488.     {
  489.     *winHeight += (*listGad) -> Height - myGad.ng_Height;  /* A bug in 2.x doesn't give the correct value */
  490.     myGad.ng_Height = (*listGad) -> Height;  /* ListView may have ended up smaller */
  491.     }
  492.  
  493. myGad.ng_LeftEdge   += sysWidth * 4 + INTERWIDTH;
  494. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT;
  495. myGad.ng_Width      = *winWidth - INTERWIDTH - myGad.ng_LeftEdge;
  496. myGad.ng_Height     = sysHeight + INTERHEIGHT;
  497. myGad.ng_GadgetID   = SLIDERGAD;
  498.  
  499. prevGad = *sliderGad = CreateGadget(SLIDER_KIND, prevGad, &myGad,
  500.                                     GTSL_Min,           -25,
  501.                                     GTSL_Max,           25,
  502.                                     GTSL_Level,         0,
  503.                                     GTSL_LevelFormat,   "%4ld",
  504.                                     GTSL_MaxLevelLen,   4,
  505.                                     GTSL_LevelPlace,    PLACETEXT_LEFT,
  506.                                     GA_RelVerify,       TRUE,
  507.                                     GA_Disabled,        TRUE,
  508.                                     TAG_END);
  509.  
  510. myGad.ng_LeftEdge   = INTERWIDTH;
  511. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT;
  512. myGad.ng_Width      = buttonText;
  513. myGad.ng_Height     = height + INTERHEIGHT;
  514. myGad.ng_GadgetText = "Break";
  515. myGad.ng_TextAttr   = propName;
  516. myGad.ng_GadgetID   = BREAKGAD;
  517.  
  518. prevGad = *breakGad = CreateGadget(BUTTON_KIND, prevGad, &myGad,
  519.                                     GA_Disabled, TRUE,
  520.                                     TAG_END);
  521.  
  522. myGad.ng_LeftEdge   += buttonText + (*winWidth - INTERWIDTH *2 - buttonText * 3) / 2;
  523. myGad.ng_GadgetText = "Kill";
  524. myGad.ng_GadgetID   = KILLGAD;
  525.  
  526. prevGad = *killGad = CreateGadget(BUTTON_KIND, prevGad, &myGad,
  527.                                     GA_Disabled, TRUE,
  528.                                     TAG_END);
  529.  
  530. myGad.ng_LeftEdge   += buttonText + (*winWidth - INTERWIDTH *2 - buttonText * 3) / 2;
  531. myGad.ng_GadgetText = "Settings...";
  532. myGad.ng_GadgetID   = SETTINGSGAD;
  533.  
  534. prevGad = CreateGadget(BUTTON_KIND, prevGad, &myGad, TAG_END);
  535.  
  536. if (prevGad)
  537.     {
  538.     if (*mainWindow)  /* it may already be open and just needs updating */
  539.         {
  540.         blank.Width = *winWidth - INTERWIDTH * 3 / 2;  /* don't blank borders */
  541.         blank.Height = *winHeight - *windowTop - INTERHEIGHT * 2 - 2;
  542.         EraseImage((*mainWindow) -> RPort, &blank, INTERWIDTH, *windowTop);
  543.         RefreshWindowFrame(*mainWindow);  /* because it's probably a mess by now... */
  544.  
  545.         AddGList(*mainWindow, *mainGads, ~0, -1, NULL);
  546.         RefreshGList(*mainGads, *mainWindow, NULL, -1);
  547.         }
  548.     else
  549.         *mainWindow = OpenWindowTags(NULL, WA_Title,    "Task Priority Manager",
  550.                                         WA_Gadgets,     *mainGads,
  551.                                         WA_Left,        winLeft,
  552.                                         WA_Top,         winTop,
  553.                                         WA_Width,       *winWidth,
  554.                                         WA_Height,      *winHeight,
  555.                                         WA_MinWidth,    minWidth,
  556.                                         WA_MinHeight,   minHeight,
  557.                                         WA_MaxWidth,    ~0,
  558.                                         WA_MaxHeight,   ~0,
  559.                                         WA_DragBar,     TRUE,
  560.                                         WA_DepthGadget, TRUE,
  561.                                         WA_CloseGadget, TRUE,
  562.                                         WA_SizeGadget,  TRUE,
  563.                                         WA_SizeBBottom, TRUE,
  564.                                         WA_Activate,    TRUE,
  565.                                         WA_RMBTrap,     TRUE,
  566.                                         WA_PubScreen,   myScreen,
  567.                                         TAG_END);
  568.  
  569.     if (*mainWindow)  /* either just opened, or else we added the gadget list above */
  570.         {
  571.         (*mainWindow) -> UserPort = port;
  572.         ModifyIDCMP(*mainWindow, WINDOWIDCMP);
  573.         GT_RefreshWindow(*mainWindow, NULL);
  574.         }
  575.     else
  576.         {
  577.         error = MAIN_ERROR;
  578.         FreeGadgets(*mainGads);
  579.         }
  580.     }
  581. else
  582.     {
  583.     error = GADGET_ERROR;
  584.     FreeGadgets(*mainGads);
  585.     }
  586. }
  587.  
  588.  
  589. /*
  590.     Layout the gadgets for the settings window, and open it.
  591. */
  592.  
  593. void openSettingsWindow(struct Window *mainWindow, struct Window **setWindow, struct Screen *myScreen,
  594.                         struct Gadget **setGads, struct Gadget **propFontGad, struct Gadget **monoFontGad,
  595.                         struct Gadget **confirmGad, struct Gadget **iconifyGad,
  596.                         struct Gadget **comGad, struct Gadget **popupGad,
  597.                         struct Gadget **hotkeyGad, struct Gadget **priorityGad,
  598.                         struct TextFont *propFont, struct TextAttr *propName, struct TextAttr *monoName,
  599.                         int height, int sysHeight, int sysWidth, int workbench,
  600.                         int *newPropFont, int *newMonoFont,
  601.                         struct MsgPort *port, void *visInfo,
  602.                         WORD windowTop, WORD *tempPropSize, WORD *tempMonoSize,
  603.                         WORD confirm, WORD *tempConfirm, WORD iconify, WORD *tempIconify,
  604.                         WORD commodity, WORD *tempCommodity, WORD popup, WORD *tempPopup,
  605.                         char *hotkey, BYTE *priority,
  606.                         char *propString, char *monoString, char *tempPropName, char *tempMonoName)
  607.  
  608. {
  609. struct RastPort     myRast;
  610. struct NewGadget    myGad;
  611. struct Gadget       *prevGad;
  612. WORD                fontText, comText, priText, cancelText, size, button, text, max, comStart, comEnd;  /* various dimensions */
  613.  
  614. *newPropFont    = *newMonoFont = 0;
  615. *tempConfirm    = confirm;  /* so we can restore it if the user clicks "Cancel" */
  616. *tempIconify    = iconify;
  617. *tempCommodity  = commodity;
  618. *tempPopup      = popup;
  619. fontString(propName, propString);  /* initial setting for the text box */
  620. fontString(monoName, monoString);
  621. strcpy(tempPropName, propName -> ta_Name);  /* initial setting for the font requester */
  622. strcpy(tempMonoName, monoName -> ta_Name);
  623. *tempPropSize = propName -> ta_YSize;
  624. *tempMonoSize = monoName -> ta_YSize;
  625.  
  626. InitRastPort(&myRast);
  627. myRast.Font = propFont;
  628.  
  629. size        = osver < 39 ? 11 : (height > 10 ? height : 11);  /* final size of button */
  630. button      = height > size ? (height - size) / 2 : 0;  /* amount button needs to be moved below text */
  631. text        = size > height ? (size - height) / 2 : 0;  /* amount text needs to be moved below button */
  632. max         = height > size ? height : size;  /* spacing between them */
  633.  
  634. fontText    = TextLength(&myRast, "Gadget Font...", 14) + INTERWIDTH * 2;
  635. comText     = TextLength(&myRast, "Commodity Options", 17);
  636. priText     = TextLength(&myRast, "Priority", 8);
  637. cancelText  = TextLength(&myRast, "Cancel", 6) + INTERWIDTH * 2;
  638.  
  639. *setGads = NULL;
  640. prevGad = CreateContext(setGads);
  641.  
  642. myGad.ng_LeftEdge   = INTERWIDTH;
  643. myGad.ng_TopEdge    = windowTop;
  644. myGad.ng_Width      = fontText;
  645. myGad.ng_Height     = height + INTERHEIGHT;
  646. myGad.ng_GadgetText = "Gadget Font...";
  647. myGad.ng_GadgetID   = GFONTGAD;
  648. myGad.ng_TextAttr   = propName;
  649. myGad.ng_Flags      = NULL;
  650. myGad.ng_VisualInfo = visInfo;
  651.  
  652. prevGad = CreateGadget(BUTTON_KIND, prevGad, &myGad, TAG_END);
  653.  
  654. myGad.ng_LeftEdge   += fontText + INTERWIDTH;
  655. myGad.ng_Width      = mainWindow -> Width - myGad.ng_LeftEdge - INTERWIDTH;
  656. myGad.ng_GadgetText = NULL;
  657. myGad.ng_GadgetID   = GBOXGAD;
  658.  
  659. prevGad = *propFontGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  660.                                         GTTX_Border,    TRUE,
  661.                                         GTTX_Text,      propString,
  662.                                         TAG_END);
  663.  
  664. myGad.ng_LeftEdge   = INTERWIDTH;
  665. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT;
  666. myGad.ng_Width      = fontText;
  667. myGad.ng_GadgetText = "List Font...";
  668. myGad.ng_GadgetID   = LFONTGAD;
  669.  
  670. prevGad = CreateGadget(BUTTON_KIND, prevGad, &myGad, TAG_END);
  671.  
  672. myGad.ng_LeftEdge   += fontText + INTERWIDTH;
  673. myGad.ng_Width      = mainWindow -> Width - myGad.ng_LeftEdge - INTERWIDTH;
  674. myGad.ng_GadgetText = NULL;
  675. myGad.ng_GadgetID   = LBOXGAD;
  676.  
  677. prevGad = *monoFontGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  678.                                         GTTX_Border,    TRUE,
  679.                                         GTTX_Text,      monoString,
  680.                                         TAG_END);
  681.  
  682. myGad.ng_LeftEdge   = INTERWIDTH;
  683. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT + button;  /* want checkbox and text centered */
  684. myGad.ng_Width      = 26;
  685. myGad.ng_Height     = size;
  686. myGad.ng_GadgetID   = CONFIRMGAD;
  687.  
  688. prevGad = *confirmGad = CreateGadget(CHECKBOX_KIND, prevGad, &myGad,
  689.                                         GTCB_Scaled,    TRUE,  /* new in 3.0 */
  690.                                         GTCB_Checked,   confirm,
  691.                                         TAG_END);
  692.  
  693. myGad.ng_LeftEdge   += myGad.ng_Width + INTERWIDTH;
  694. myGad.ng_TopEdge    += text - button;
  695. myGad.ng_Width      = NULL;  /* let it figure it out for itself... */
  696. myGad.ng_Height     = height;
  697. myGad.ng_GadgetID   = NULL;
  698.  
  699. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  700.                         GTTX_Text,  "Confirm actions",
  701.                         TAG_END);
  702.  
  703. myGad.ng_LeftEdge   = INTERWIDTH;
  704. myGad.ng_TopEdge    += max + INTERHEIGHT - text + button;
  705. myGad.ng_Width      = 26;
  706. myGad.ng_Height     = size;
  707. myGad.ng_GadgetID   = ICONIFYGAD;
  708.  
  709. prevGad = *iconifyGad = CreateGadget(CHECKBOX_KIND, prevGad, &myGad,
  710.                                         GTCB_Scaled,    TRUE,
  711.                                         GTCB_Checked,   iconify,
  712.                                         GA_Disabled,    !workbench,  /* because we won't know where to get the image from */
  713.                                         TAG_END);
  714.  
  715. myGad.ng_LeftEdge   += myGad.ng_Width + INTERWIDTH;
  716. myGad.ng_TopEdge    += text - button;
  717. myGad.ng_Width      = NULL;
  718. myGad.ng_Height     = height;
  719. myGad.ng_GadgetID   = NULL;
  720.  
  721. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  722.                         GTTX_Text,  "Iconify when closed",
  723.                         TAG_END);
  724.  
  725. myGad.ng_LeftEdge   = (mainWindow -> Width - comText) / 2;  /* centred */
  726. myGad.ng_TopEdge    += max + INTERHEIGHT * 2 - text;
  727. myGad.ng_Width      = NULL;
  728.  
  729. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  730.                         GTTX_Text,  "Commodity Options",
  731.                         TAG_END);
  732.  
  733. myGad.ng_LeftEdge   = INTERWIDTH * 2;
  734. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT * 2 + button;
  735. myGad.ng_Width      = 26;
  736. myGad.ng_Height     = size;
  737. myGad.ng_GadgetID   = COMGAD;
  738.  
  739. comStart = myGad.ng_TopEdge - button;
  740.  
  741. prevGad = *comGad = CreateGadget(CHECKBOX_KIND, prevGad, &myGad,
  742.                                     GTCB_Scaled,    TRUE,
  743.                                     GTCB_Checked,   commodity,
  744.                                     TAG_END);
  745.  
  746. myGad.ng_LeftEdge   += myGad.ng_Width + INTERWIDTH;
  747. myGad.ng_TopEdge    += text - button;
  748. myGad.ng_Width      = NULL;
  749. myGad.ng_Height     = height;
  750. myGad.ng_GadgetID   = NULL;
  751.  
  752. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  753.                         GTTX_Text,  "Install as a Commodity",
  754.                         TAG_END);
  755.  
  756. myGad.ng_LeftEdge   = INTERWIDTH * 2;
  757. myGad.ng_TopEdge    += max + INTERHEIGHT - text + button;
  758. myGad.ng_Width      = 26;
  759. myGad.ng_Height     = size;
  760. myGad.ng_GadgetID   = POPUPGAD;
  761.  
  762. prevGad = *popupGad = CreateGadget(CHECKBOX_KIND, prevGad, &myGad,
  763.                                     GTCB_Scaled,    TRUE,
  764.                                     GTCB_Checked,   popup,
  765.                                     GA_Disabled,    !commodity,
  766.                                     TAG_END);
  767.  
  768. myGad.ng_LeftEdge   += myGad.ng_Width + INTERWIDTH;
  769. myGad.ng_TopEdge    += text - button;
  770. myGad.ng_Width      = NULL;
  771. myGad.ng_Height     = height;
  772. myGad.ng_GadgetID   = NULL;
  773.  
  774. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  775.                         GTTX_Text,  "Popup when launched",
  776.                         TAG_END);
  777.  
  778. myGad.ng_LeftEdge   = INTERWIDTH * 2;
  779. myGad.ng_TopEdge    += max - text + INTERHEIGHT * 3 / 2 + 1;
  780.  
  781. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  782.                         GTTX_Text, "Hotkey",
  783.                         TAG_END);
  784.  
  785. myGad.ng_LeftEdge   += priText + INTERWIDTH;
  786. myGad.ng_TopEdge    -= INTERHEIGHT / 2 + 1;
  787. myGad.ng_Width      = mainWindow -> Width - priText - INTERWIDTH * 5;
  788. myGad.ng_Height     = height + INTERHEIGHT + 2;
  789. myGad.ng_GadgetID   = HOTKEYGAD;
  790.  
  791. prevGad = *hotkeyGad = CreateGadget(STRING_KIND, prevGad, &myGad,
  792.                                     GTST_String,    hotkey,
  793.                                     GTST_MaxChars,  MaxHotkey,
  794.                                     GA_Disabled,    !commodity,
  795.                                     TAG_END);
  796.  
  797. myGad.ng_LeftEdge   = INTERWIDTH * 2;
  798. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT * 3 / 2 + 1;
  799. myGad.ng_Width      = NULL,
  800. myGad.ng_Height     = height;
  801. myGad.ng_GadgetID   = NULL;
  802.  
  803. prevGad = CreateGadget(TEXT_KIND, prevGad, &myGad,
  804.                         GTTX_Text, "Priority",
  805.                         TAG_END);
  806.  
  807. myGad.ng_LeftEdge   += priText + INTERWIDTH;
  808. myGad.ng_TopEdge    -= INTERHEIGHT / 2 + 1;
  809. myGad.ng_Width      = priText + INTERWIDTH;  /* for lack of a better width... */
  810. myGad.ng_Height     = height + INTERHEIGHT + 2;
  811. myGad.ng_GadgetID   = PRIORITYGAD;
  812.  
  813. prevGad = *priorityGad = CreateGadget(INTEGER_KIND, prevGad, &myGad,
  814.                                         GTIN_Number,    *priority,
  815.                                         GTIN_MaxChars,  4,  /* e.g., -128 */
  816.                                         GA_Disabled,    !commodity,
  817.                                         TAG_END);
  818.  
  819. myGad.ng_LeftEdge   = INTERWIDTH;
  820. myGad.ng_TopEdge    += myGad.ng_Height + INTERHEIGHT * 3;
  821. myGad.ng_Width      = cancelText;
  822. myGad.ng_Height     = height + INTERHEIGHT;
  823. myGad.ng_GadgetText = "Save";
  824. myGad.ng_GadgetID   = SAVEGAD;
  825.  
  826. comEnd = myGad.ng_TopEdge;
  827.  
  828. prevGad = CreateGadget(BUTTON_KIND, prevGad, &myGad,
  829.                         GA_Disabled,    !workbench,  /* nowhere to write out the settings! */
  830.                         TAG_END);
  831.  
  832. myGad.ng_LeftEdge   += cancelText + (mainWindow -> Width - INTERWIDTH *2 - cancelText * 3) / 2;
  833. myGad.ng_GadgetText = "Use";
  834. myGad.ng_GadgetID   = USEGAD;
  835.  
  836. prevGad = CreateGadget(BUTTON_KIND, prevGad, &myGad, TAG_END);
  837.  
  838. myGad.ng_LeftEdge   += cancelText + (mainWindow -> Width - INTERWIDTH *2 - cancelText * 3) / 2;
  839. myGad.ng_GadgetText = "Cancel";
  840. myGad.ng_GadgetID   = CANCELGAD;
  841.  
  842. prevGad = CreateGadget(BUTTON_KIND, prevGad, &myGad, TAG_END);
  843.  
  844. if (prevGad)
  845.     {
  846.     if (*setWindow = OpenWindowTags(NULL,   WA_Title,       "PriMan Settings",
  847.                                             WA_Gadgets,     *setGads,
  848.                                             WA_Left,        mainWindow -> LeftEdge,
  849.                                             WA_Top,         mainWindow -> TopEdge + windowTop - INTERHEIGHT,
  850.                                             WA_Width,       mainWindow -> Width,
  851.                                             WA_Height,      myGad.ng_TopEdge + myGad.ng_Height + INTERHEIGHT + 2,
  852.                                             WA_DragBar,     TRUE,
  853.                                             WA_DepthGadget, TRUE,
  854.                                             WA_Activate,    TRUE,
  855.                                             WA_CloseGadget, TRUE,
  856.                                             WA_RMBTrap,     TRUE,
  857.                                             WA_PubScreen,   myScreen,
  858.                                             TAG_END))
  859.         {
  860.         (*setWindow) -> UserPort = port;
  861.         ModifyIDCMP(*setWindow, WINDOWIDCMP);
  862.         DrawBevelBox((*setWindow) -> RPort, INTERWIDTH, comStart - INTERHEIGHT,
  863.                         mainWindow -> Width - INTERWIDTH * 2, comEnd - comStart - INTERHEIGHT,
  864.                         GTBB_Recessed,  TRUE,
  865.                         GT_VisualInfo,  visInfo,
  866.                         TAG_END);
  867.         GT_RefreshWindow(*setWindow, NULL);
  868.         }
  869.     else
  870.         {
  871.         error = SETTINGS_ERROR;
  872.         FreeGadgets(*setGads);
  873.         }
  874.     }
  875. else
  876.     {
  877.     error = GADGET_ERROR;
  878.     FreeGadgets(*setGads);
  879.     }
  880. }
  881.  
  882.  
  883. /*
  884.     Generate the task list, and place it in the main window's ListView.
  885. */
  886.  
  887. void createList(struct List *taskList, struct Remember **memoryKey, struct Window *mainWindow, int taskLength,
  888.                 struct Gadget *listGad, struct Gadget *sliderGad, struct Gadget *breakGad, struct Gadget *killGad)
  889. {
  890. struct Task     *taskArray[MaxTasks];  /* one kilobyte worth of pointers should be enough! */
  891. int             taskCount;
  892. struct Node     *execNode;
  893. struct listType *taskNode;
  894.  
  895. GT_SetGadgetAttrs(listGad, mainWindow, NULL,
  896.                     GTLV_Labels,    ~0,
  897.                     TAG_END);
  898. FreeRemember(memoryKey, TRUE);  /* can't hurt even if it's NULL */
  899.  
  900. taskArray[0] = FindTask(NULL);  /* us */
  901. taskCount = 1;  /* first element was this task */
  902.  
  903. Disable();  /* going to walk Exec's task list */
  904. for (execNode = SysBase -> TaskReady.lh_Head; execNode -> ln_Succ && taskCount < MaxTasks; execNode = execNode -> ln_Succ)
  905.     taskArray[taskCount++] = (struct Task *)execNode;
  906. for (execNode = SysBase -> TaskWait.lh_Head; execNode -> ln_Succ && taskCount < MaxTasks; execNode = execNode -> ln_Succ)
  907.     taskArray[taskCount++] = (struct Task *)execNode;
  908. Enable();
  909.  
  910. taskList -> lh_Head     = (struct Node *) &(taskList -> lh_Tail);
  911. taskList -> lh_Tail     = NULL;
  912. taskList -> lh_TailPred = (struct Node *) &(taskList -> lh_Head);
  913.  
  914. while (taskCount-- > 0 && !error)
  915.     {
  916.     if ((taskNode = AllocRemember(memoryKey, sizeof(struct listType), MEMF_ANY))
  917.         && (taskNode -> mainNode.ln_Name = AllocRemember(memoryKey, taskLength + 1, MEMF_ANY)))
  918.         {
  919.         if (taskArray[taskCount] -> tc_State > 1 && taskArray[taskCount] -> tc_State < 5)  /* task hasn't gone away in the meantime */
  920.             {
  921.             createString(taskArray[taskCount], taskNode -> mainNode.ln_Name, taskLength);
  922.             taskNode -> mainNode.ln_Pri = taskArray[taskCount] -> tc_Node.ln_Pri;
  923.             taskNode -> mainTask = taskArray[taskCount];
  924.             for (execNode = taskList -> lh_Head; (execNode -> ln_Succ) && Compare(execNode -> ln_Name, taskNode -> mainNode.ln_Name) < 0; execNode = execNode -> ln_Succ)
  925.                 ;
  926.             Insert(taskList, (struct Node *)taskNode, execNode -> ln_Pred);
  927.             }
  928.         }
  929.     else
  930.         {
  931.         error = TASK_ERROR;
  932.         FreeRemember(memoryKey, TRUE);
  933.         }
  934.     }
  935.  
  936. if (!error)
  937.     {
  938.     GT_SetGadgetAttrs(listGad, mainWindow, NULL,
  939.                         GTLV_Labels,    taskList,
  940.                         GTLV_Selected,  ~0,
  941.                         TAG_END);
  942.     GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
  943.                         GA_Disabled,    TRUE,
  944.                         TAG_END);
  945.     GT_SetGadgetAttrs(breakGad, mainWindow, NULL,
  946.                         GA_Disabled,    TRUE,
  947.                         TAG_END);
  948.     GT_SetGadgetAttrs(killGad, mainWindow, NULL,
  949.                         GA_Disabled,    TRUE,
  950.                         TAG_END);
  951.     }
  952. }
  953.  
  954.  
  955. /*
  956.     Process an input event from the main window.
  957. */
  958.  
  959. void handleMainWindow(ULONG class, WORD code, struct Gadget *selectedGad,
  960.                         struct Window *mainWindow, struct Window *setWindow, struct Gadget *mainGads,
  961.                         WORD *winLeft, WORD *winTop, WORD *winWidth, WORD *winHeight,
  962.                         struct Gadget *listGad, struct Gadget *sliderGad,
  963.                         struct Gadget *breakGad, struct Gadget *killGad,
  964.                         int *pos, int *wide, WORD confirm,
  965.                         struct Node **current, struct List *taskList, int taskLength)
  966. {
  967. struct Task         *currentTask;
  968. struct List         windowList;
  969. struct Remember     *windowKey;
  970. struct Node         *node;
  971. struct Screen       *screen;
  972. struct Window       *window;
  973. struct Requester    req1, req2;
  974. ULONG               ibase;
  975. int                 button;
  976.  
  977. struct EasyStruct suicide =  /* Dream on... */
  978.     {
  979.     sizeof(struct EasyStruct),
  980.     0,
  981.     "PriMan suicide",
  982.     "You can't do that!!",
  983.     "Whoops"
  984.     };
  985.  
  986. struct EasyStruct lost =  /* Oi! Where did that task go? */
  987.     {
  988.     sizeof(struct EasyStruct),
  989.     0,
  990.     "PriMan trouble",
  991.     "Task was not found!",
  992.     "Okay"
  993.     };
  994.  
  995. struct EasyStruct signal =
  996.     {
  997.     sizeof(struct EasyStruct),
  998.     0,
  999.     "PriMan warning",
  1000.     "Really signal `%s'\nwith Ctrl-C?",
  1001.     "Signal|Cancel"
  1002.     };
  1003.  
  1004. struct EasyStruct kill =
  1005.     {
  1006.     sizeof(struct EasyStruct),
  1007.     0,
  1008.     "PriMan warning",
  1009.     "Really remove `%s'?",
  1010.     "Remove|Cancel"
  1011.     };
  1012.  
  1013. struct EasyStruct close =
  1014.     {
  1015.     sizeof(struct EasyStruct),
  1016.     0,
  1017.     "PriMan query",
  1018.     "Close windows belonging\nto this task?",
  1019.     "Yes|No"
  1020.     };
  1021.  
  1022.  
  1023. switch (class)
  1024.     {
  1025.     case IDCMP_CLOSEWINDOW:
  1026.         error = CLOSE_MAIN;
  1027.         break;
  1028.  
  1029.     case IDCMP_NEWSIZE:
  1030.         error = REDRAW_MAIN;
  1031.         GetPos(mainWindow, winLeft, winTop, winWidth, winHeight);
  1032.         RemoveGList(mainWindow, mainGads, -1);
  1033.         break;
  1034.  
  1035.     case IDCMP_REFRESHWINDOW:
  1036.         GT_BeginRefresh(mainWindow);
  1037.         GT_EndRefresh(mainWindow, TRUE);
  1038.         break;
  1039.  
  1040.     case GADGETUP:
  1041.         switch (selectedGad -> GadgetID)
  1042.             {
  1043.             case LISTGAD:
  1044.                 *pos = code;
  1045.                 for (*current = taskList -> lh_Head; code > 0; *current = (*current) -> ln_Succ, code --)  /* find selected task */
  1046.                     ;
  1047.  
  1048.                 if (*wide = ((*current) -> ln_Pri < -25 || (*current) -> ln_Pri > 25))  /* wide or narrow scale? */
  1049.                     GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
  1050.                                         GTSL_Min,   -128,
  1051.                                         GTSL_Max,   127,
  1052.                                         TAG_END);
  1053.                 else
  1054.                     GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
  1055.                                         GTSL_Min,   -25,
  1056.                                         GTSL_Max,   25,
  1057.                                         TAG_END);
  1058.  
  1059.                 GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,  /* update slider gadget to new task's priority */
  1060.                                     GTSL_Level,     (*current) -> ln_Pri,
  1061.                                     GA_Disabled,    FALSE,
  1062.                                     TAG_END);
  1063.                 GT_SetGadgetAttrs(breakGad, mainWindow, NULL,
  1064.                                     GA_Disabled,    FALSE,
  1065.                                     TAG_END);
  1066.                 GT_SetGadgetAttrs(killGad, mainWindow, NULL,
  1067.                                     GA_Disabled,    FALSE,
  1068.                                     TAG_END);
  1069.                 break;
  1070.  
  1071.             case SLIDERGAD:
  1072.                 currentTask = ((struct listType *)(*current)) -> mainTask;
  1073.                 if (currentTask -> tc_State < 2 || currentTask -> tc_State > 4)  /* not a valid task */
  1074.                     {
  1075.                     busyPointer(mainWindow, setWindow, &req1, &req2);
  1076.                     EasyRequest(NULL, &lost, NULL, NULL);
  1077.                     normalPointer(mainWindow, setWindow, &req1, &req2);
  1078.                     error = UPDATE;
  1079.                     }
  1080.                 else
  1081.                     {
  1082.                     SetTaskPri(currentTask, (WORD)code);
  1083.                     GT_SetGadgetAttrs(listGad, mainWindow, NULL,
  1084.                                         GTLV_Labels,    ~0,
  1085.                                         TAG_END);
  1086.                     createString(currentTask, (*current) -> ln_Name, taskLength);
  1087.                     (*current) -> ln_Pri = (WORD)code;
  1088.                     GT_SetGadgetAttrs(listGad, mainWindow, NULL,
  1089.                                         GTLV_Labels,    taskList,
  1090.                                         GTLV_Selected,  *pos,  /* only required under 2.0 */
  1091.                                         TAG_END);
  1092.                     }
  1093.                 break;
  1094.  
  1095.             case BREAKGAD:
  1096.             case KILLGAD:
  1097.                 if (!(*pos == -1))
  1098.                     {
  1099.                     busyPointer(mainWindow, setWindow, &req1, &req2);
  1100.                     currentTask = ((struct listType *)(*current)) -> mainTask;
  1101.                     if (currentTask -> tc_State < 2 || currentTask -> tc_State > 4)  /* not a valid task */
  1102.                         {
  1103.                         EasyRequest(NULL, &lost, NULL, NULL);
  1104.                         error = UPDATE;
  1105.                         }
  1106.                     else
  1107.                         if (currentTask == FindTask(NULL))
  1108.                             EasyRequest(NULL, &suicide, NULL, NULL);
  1109.                     else
  1110.                         {
  1111.                         if (confirm)
  1112.                             button = EasyRequest(NULL, (selectedGad -> GadgetID == BREAKGAD) ? &signal : &kill, NULL, currentTask -> tc_Node.ln_Name);
  1113.                         if (button || !confirm)  /* user clicked "Okay" */
  1114.                             {
  1115.                             Disable();
  1116.                             if (currentTask -> tc_State >= 2 && currentTask -> tc_State <= 4)  /* paranoid! */
  1117.                                 {
  1118.                                 if (selectedGad -> GadgetID == BREAKGAD)
  1119.                                     {
  1120.                                     Signal(currentTask, SIGBREAKF_CTRL_C);
  1121.                                     Enable();
  1122.                                     Delay(25);  /* allow time for task to exit */
  1123.                                     }
  1124.                                 else
  1125.                                     {
  1126.                                     SetTaskPri(currentTask, -128);  /* we don't want it doing anything behind our backs... */
  1127.                                     Enable();
  1128.  
  1129.                                     windowList.lh_Head = (struct Node *) &windowList.lh_Tail;
  1130.                                     windowList.lh_Tail = NULL;
  1131.                                     windowList.lh_TailPred = (struct Node *) &windowList.lh_Head;
  1132.                                     windowKey = NULL;
  1133.                                     ibase = LockIBase(NULL);  /* going to look at all screens & windows in system */
  1134.  
  1135.                                     for (screen = IntuitionBase -> FirstScreen; screen; screen = screen -> NextScreen)
  1136.                                         for (window = screen -> FirstWindow; window; window = window -> NextWindow)
  1137.                                             if (window -> UserPort && (struct Task *)(window -> UserPort -> mp_SigTask) == currentTask)
  1138.                                                 if (node = AllocRemember(&windowKey, sizeof(struct Node), MEMF_ANY))
  1139.                                                     {
  1140.                                                     node -> ln_Name = (char *)window;  /* okay, so it's not really a name... */
  1141.                                                     AddTail(&windowList, node);
  1142.                                                     }
  1143.  
  1144.                                     UnlockIBase(ibase);  /* hopefully nothing will sneakily close any of the windows we took a note of */
  1145.                                     if (windowList.lh_Head -> ln_Succ)  /* something got added to the list */
  1146.                                         if (EasyRequest(NULL, &close, NULL, NULL))  /* shall we close these windows? */
  1147.                                             for (node = windowList.lh_Head; node -> ln_Succ; node = node -> ln_Succ)
  1148.                                                 CloseWindowSafely((struct Window *)(node -> ln_Name));
  1149.  
  1150.                                     Disable();
  1151.                                     if (currentTask -> tc_State >= 2 && currentTask -> tc_State <= 4)  /* _really_ paranoid! */
  1152.                                         RemTask(currentTask);  /* BLAM! */
  1153.                                     Enable();
  1154.                                     FreeRemember(&windowKey, TRUE);
  1155.                                     }
  1156.                                 }
  1157.                             error = UPDATE;
  1158.                             }
  1159.                         }
  1160.                     normalPointer(mainWindow, setWindow, &req1, &req2);
  1161.                     }
  1162.                 break;
  1163.  
  1164.             case SETTINGSGAD:
  1165.                 error = OPEN_SETTINGS;
  1166.                 break;
  1167.             }
  1168.         break;
  1169.  
  1170.     case RAWKEY:
  1171.         switch (code)
  1172.             {
  1173.             case 64:
  1174.             case 68:  /* Space or Return keys */
  1175.                 error = UPDATE;
  1176.                 break;
  1177.  
  1178.             case 66:  /* Tab key */
  1179.                 if (!(*pos == -1))  /* don't change the scale of a disabled slider */
  1180.                     {
  1181.                     if ((*current) -> ln_Pri > -26 && (*current) -> ln_Pri < 26)  /* don't want to end up off the scale! */
  1182.                         {
  1183.                         if (*wide = 1 - *wide)
  1184.                             GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
  1185.                                                 GTSL_Min,   -128,
  1186.                                                 GTSL_Max,   127,
  1187.                                                 TAG_END);
  1188.                         else
  1189.                             GT_SetGadgetAttrs(sliderGad, mainWindow, NULL,
  1190.                                                 GTSL_Min,   -25,
  1191.                                                 GTSL_Max,   25,
  1192.                                                 TAG_END);
  1193.                         }
  1194.                     }
  1195.                 break;
  1196.  
  1197.             case 69:  /* Escape key */
  1198.                 error = QUIT;
  1199.                 break;
  1200.  
  1201.             case 95:  /* Help key */
  1202.                 busyPointer(mainWindow, setWindow, &req1, &req2);
  1203.                 EasyRequest(NULL, &about, NULL, NULL);
  1204.                 normalPointer(mainWindow, setWindow, &req1, &req2);
  1205.                 break;
  1206.             }
  1207.         break;
  1208.     }
  1209. }
  1210.  
  1211.  
  1212. /*
  1213.     Process an input event from the settings window.
  1214. */
  1215.  
  1216. void handleSettingsWindow(ULONG class, WORD code, struct MsgPort *port, struct Gadget *selectedGad,
  1217.                             struct Window *mainWindow, struct Window *setWindow,
  1218.                             WORD *tempPropSize, WORD *tempMonoSize, WORD *confirm, WORD *tempConfirm,
  1219.                             WORD *iconify, WORD *tempIconify, WORD iconLeft, WORD iconTop,
  1220.                             WORD *commodity, WORD *tempCommodity, WORD *popup, WORD *tempPopup,
  1221.                             char *hotkey, BYTE *priority,
  1222.                             struct FontRequester *propFontReq, struct FontRequester *monoFontReq,
  1223.                             struct Gadget *propFontGad, struct Gadget *monoFontGad,
  1224.                             struct Gadget *popupGad, struct Gadget *hotkeyGad, struct Gadget *priorityGad,
  1225.                             struct TextAttr *propName, struct TextAttr *monoName,
  1226.                             char *propString, char *monoString, char *tempPropName, char *tempMonoName,
  1227.                             char *myName, WORD windowTop, int *newPropFont, int *newMonoFont,
  1228.                             struct NewBroker *newBroker, CxObj **broker, CxObj **filter, CxObj **sender, CxObj **translate)
  1229. {
  1230. struct DiskObject   *myIcon;
  1231. struct Requester    req1, req2;
  1232. char                **oldTools, **currentTool, *newTools[20], empty[16][MAXFONTNAME + 10], *string;
  1233. int                 oldPos, newPos;
  1234.  
  1235. switch (class)
  1236.     {
  1237.     case IDCMP_CLOSEWINDOW:
  1238.         error = CLOSE_SETTINGS;
  1239.         break;
  1240.  
  1241.     case IDCMP_REFRESHWINDOW:
  1242.         GT_BeginRefresh(setWindow);
  1243.         GT_EndRefresh(setWindow, TRUE);
  1244.         break;
  1245.  
  1246.     case GADGETUP:
  1247.         switch (selectedGad -> GadgetID)
  1248.             {
  1249.             case CONFIRMGAD:
  1250.                 *tempConfirm = (selectedGad -> Flags) & GFLG_SELECTED;
  1251.                 break;
  1252.  
  1253.             case ICONIFYGAD:
  1254.                 *tempIconify = (selectedGad -> Flags) & GFLG_SELECTED;
  1255.                 break;
  1256.  
  1257.             case COMGAD:
  1258.                 *tempCommodity = (selectedGad -> Flags) & GFLG_SELECTED;
  1259.                 GT_SetGadgetAttrs(popupGad, setWindow, NULL,
  1260.                                     GA_Disabled,    !*tempCommodity,
  1261.                                     TAG_END);
  1262.                 GT_SetGadgetAttrs(hotkeyGad, setWindow, NULL,
  1263.                                     GA_Disabled,    !*tempCommodity,
  1264.                                     TAG_END);
  1265.                 GT_SetGadgetAttrs(priorityGad, setWindow, NULL,
  1266.                                     GA_Disabled,    !*tempCommodity,
  1267.                                     TAG_END);
  1268.                 break;
  1269.  
  1270.             case POPUPGAD:
  1271.                 *tempPopup = (selectedGad -> Flags) & GFLG_SELECTED;
  1272.                 break;
  1273.  
  1274.             case GFONTGAD:
  1275.                 busyPointer(mainWindow, setWindow, &req1, &req2);
  1276.                 if (*newPropFont = AslRequestTags(propFontReq,  ASL_Hail,       "Select Gadget Font",
  1277.                                                                 ASL_FuncFlags,  NULL,
  1278.                                                                 ASL_LeftEdge,   setWindow -> LeftEdge,
  1279.                                                                 ASL_TopEdge,    setWindow -> TopEdge + windowTop - INTERHEIGHT,
  1280.                                                                 ASL_FontName,   tempPropName,
  1281.                                                                 ASL_FontHeight, *tempPropSize,
  1282.                                                                 TAG_END))
  1283.                     {
  1284.                     fontString(&(propFontReq -> fo_Attr), propString);
  1285.                     GT_SetGadgetAttrs(propFontGad, setWindow, NULL,
  1286.                                         GTTX_Text, propString,
  1287.                                         TAG_END);
  1288.                     strcpy(tempPropName, propFontReq -> fo_Attr.ta_Name);
  1289.                     *tempPropSize = propFontReq -> fo_Attr.ta_YSize;
  1290.                     }
  1291.                 normalPointer(mainWindow, setWindow, &req1, &req2);
  1292.                 break;
  1293.  
  1294.             case LFONTGAD:
  1295.                 busyPointer(mainWindow, setWindow, &req1, &req2);
  1296.                 if (*newMonoFont = AslRequestTags(monoFontReq,  ASL_Hail,       "Select Task List Font",
  1297.                                                                 ASL_FuncFlags,  FONF_FIXEDWIDTH,
  1298.                                                                 ASL_LeftEdge,   setWindow -> LeftEdge,
  1299.                                                                 ASL_TopEdge,    setWindow -> TopEdge + windowTop - INTERHEIGHT,
  1300.                                                                 ASL_FontName,   tempMonoName,
  1301.                                                                 ASL_FontHeight, *tempMonoSize,
  1302.                                                                 TAG_END))
  1303.                     {
  1304.                     fontString(&(monoFontReq -> fo_Attr), monoString);
  1305.                     GT_SetGadgetAttrs(monoFontGad, setWindow, NULL,
  1306.                                         GTTX_Text, monoString,
  1307.                                         TAG_END);
  1308.                     strcpy(tempMonoName, monoFontReq -> fo_Attr.ta_Name);
  1309.                     *tempMonoSize = monoFontReq -> fo_Attr.ta_YSize;
  1310.                     }
  1311.                 normalPointer(mainWindow, setWindow, &req1, &req2);
  1312.                 break;
  1313.  
  1314.             case SAVEGAD:
  1315.             case USEGAD:
  1316.                 busyPointer(mainWindow, setWindow, &req1, &req2);  /* there may be a delay writing out to disk */
  1317.                 error = CLOSE_SETTINGS;
  1318.  
  1319.                 strcpy(hotkey, ((struct StringInfo *)hotkeyGad -> SpecialInfo) -> Buffer);
  1320.                 if (*commodity && *tempCommodity)  /* going to stick around */
  1321.                     {
  1322.                     SetFilter(*filter, hotkey);  /* just in case it changed... */
  1323.                     if (CxObjError(*filter) == COERR_BADFILTER)
  1324.                         EasyRequest(NULL, &badFilter, NULL, NULL);
  1325.                     }
  1326.  
  1327.                 else if (*tempCommodity)  /* and it wasn't already a commodity */
  1328.                     setupCommodity(hotkey, port, mainWindow, setWindow,
  1329.                                     newBroker, broker, filter, sender, translate);
  1330.  
  1331.                 else  /* may or may not have been a commodity, but it's not wanted anyway... */
  1332.                     {
  1333.                     DeleteCxObjAll(*broker);
  1334.                     *broker = NULL;
  1335.                     }
  1336.  
  1337.                 *confirm    = *tempConfirm;
  1338.                 *iconify    = *tempIconify;
  1339.                 *commodity  = *tempCommodity;
  1340.                 *popup      = *tempPopup;
  1341.                 *priority   = ((struct StringInfo *)priorityGad -> SpecialInfo) -> LongInt;
  1342.  
  1343.                 if (*newPropFont && (strcmp((propFontReq -> fo_Attr).ta_Name, propName -> ta_Name)
  1344.                                     || !((propFontReq -> fo_Attr).ta_YSize == propName -> ta_YSize)))
  1345.                     {
  1346.                     strcpy(propName -> ta_Name, (propFontReq -> fo_Attr).ta_Name);
  1347.                     propName -> ta_YSize = (propFontReq -> fo_Attr).ta_YSize;
  1348.                     error = NEW_FONT;
  1349.                     }
  1350.  
  1351.                 if (*newMonoFont && (strcmp((monoFontReq -> fo_Attr).ta_Name, monoName -> ta_Name)
  1352.                                     || !((monoFontReq -> fo_Attr).ta_YSize == monoName -> ta_YSize)))
  1353.                     {
  1354.                     strcpy(monoName -> ta_Name, (monoFontReq -> fo_Attr).ta_Name);
  1355.                     monoName -> ta_YSize = (monoFontReq -> fo_Attr).ta_YSize;
  1356.                     error = NEW_FONT;
  1357.                     }
  1358.  
  1359.                 if (selectedGad -> GadgetID == SAVEGAD)
  1360.                     {
  1361.                     if (myIcon = GetDiskObject(myName));
  1362.                         {
  1363.                         currentTool = oldTools = myIcon -> do_ToolTypes;  /* existing ToolTypes */
  1364.  
  1365.                         oldPos = newPos = 0;
  1366.                         while (string = currentTool[oldPos++])
  1367.                             if (strncmp(string, "COMMODITY", 9) && strncmp(string, "CX_POPUP", 8)
  1368.                                 && strncmp(string, "CX_POPKEY", 9) && strncmp(string, "CX_PRIORITY", 11)
  1369.                                 && strncmp(string, "LEFT", 4) && strncmp(string, "TOP", 3)
  1370.                                 && strncmp(string, "WIDTH", 5) && strncmp(string, "HEIGHT", 6)
  1371.                                 && strncmp(string, "GADFONT", 7) && strncmp(string, "GADSIZE", 7)
  1372.                                 && strncmp(string, "LISTFONT", 8) && strncmp(string, "LISTSIZE", 8)
  1373.                                 && strncmp(string, "ICONLEFT", 8) && strncmp(string, "ICONTOP", 7)
  1374.                                 && strncmp(string, "CONFIRM", 7) && strncmp(string, "ICONIFY", 7))  /* get rid of our ones */
  1375.                                 newTools[newPos++] = string;
  1376.  
  1377.                         sprintf(empty[0], "COMMODITY=%s", *commodity ? "YES" : "NO");
  1378.                         sprintf(empty[1], "CX_POPUP=%s", *popup ? "YES" : "NO");
  1379.                         sprintf(empty[2], "CX_POPKEY=%s", hotkey);
  1380.                         sprintf(empty[3], "CX_PRIORITY=%d", *priority);
  1381.                         sprintf(empty[4], "LEFT=%d", mainWindow -> LeftEdge);
  1382.                         sprintf(empty[5], "TOP=%d", mainWindow -> TopEdge);
  1383.                         sprintf(empty[6], "WIDTH=%d", mainWindow -> Width);
  1384.                         sprintf(empty[7], "HEIGHT=%d", mainWindow -> Height);
  1385.                         sprintf(empty[8], "GADFONT=%s", propName -> ta_Name);
  1386.                         sprintf(empty[9], "GADSIZE=%d", propName -> ta_YSize);
  1387.                         sprintf(empty[10], "LISTFONT=%s", monoName -> ta_Name);
  1388.                         sprintf(empty[11], "LISTSIZE=%d", monoName -> ta_YSize);
  1389.                         sprintf(empty[12], "ICONLEFT=%d", iconLeft);
  1390.                         sprintf(empty[13], "ICONTOP=%d", iconTop);
  1391.                         sprintf(empty[14], "CONFIRM=%s", *confirm ? "YES" : "NO");
  1392.                         sprintf(empty[15], "ICONIFY=%s", *iconify ? "YES" : "NO");
  1393.  
  1394.                         for (oldPos = 0; oldPos < 16;)
  1395.                             newTools[newPos++] = empty[oldPos++];  /* write out our ones at end */
  1396.  
  1397.                         newTools[newPos] = NULL;  /* end of list */
  1398.                         myIcon -> do_ToolTypes = newTools;
  1399.                         PutDiskObject(myName, myIcon);
  1400.                         myIcon -> do_ToolTypes = oldTools;  /* restore original pointer before freeing memory */
  1401.                         FreeDiskObject(myIcon);
  1402.                         }
  1403.                     }
  1404.                 normalPointer(mainWindow, setWindow, &req1, &req2);
  1405.                 break;
  1406.  
  1407.             case CANCELGAD:
  1408.                 error = CLOSE_SETTINGS;
  1409.                 break;
  1410.             }
  1411.         break;
  1412.  
  1413.     case RAWKEY:
  1414.         switch (code)
  1415.             {
  1416.             case 69:  /* Escape key */
  1417.                 error = QUIT;
  1418.                 break;
  1419.  
  1420.             case 95:  /* Help key */
  1421.                 busyPointer(mainWindow, setWindow, &req1, &req2);
  1422.                 EasyRequest(NULL, &about, NULL, NULL);
  1423.                 normalPointer(mainWindow, setWindow, &req1, &req2);
  1424.                 break;
  1425.             }
  1426.         break;
  1427.     }
  1428. }
  1429.  
  1430.  
  1431. /*
  1432.     The main loop. Wait for messages to arrive at our port, and call relevant procedures.
  1433. */
  1434.  
  1435. void handleMessages(int argc, char *argv[])
  1436. {
  1437. struct FontRequester    *propFontReq, *monoFontReq;
  1438.  
  1439. struct DiskObject   *myIcon = NULL, *wbIcon = NULL;
  1440. struct AppIcon      *appIcon = NULL;
  1441. struct MsgPort      *port;
  1442. struct Screen       *myScreen = NULL;
  1443. struct Window       *mainWindow = NULL, *setWindow = NULL, *window;
  1444. struct TextFont     *propFont = NULL, *monoFont = NULL;
  1445. struct Message      *message;
  1446. struct IntuiMessage *imsg;
  1447. struct List         taskList;
  1448. struct Remember     *memoryKey = 0;
  1449. struct Node         *current;
  1450. struct Gadget       *mainGads = 0, *setGads = 0, *selectedGad,
  1451.                     *listGad = 0, *sliderGad = 0, *breakGad = 0, *killGad = 0,
  1452.                     *propFontGad = 0, *monoFontGad = 0, *confirmGad, *iconifyGad,
  1453.                     *comGad, *popupGad = 0, *hotkeyGad = 0, *priorityGad = 0;
  1454. struct TextAttr     propName = { "                                 ", 0, 0, 0 },
  1455.                     monoName = { "                                 ", 0, 0, 0 };
  1456.  
  1457. CxObj   *broker = NULL, *filter, *sender, *translate;
  1458. void    *visInfo = NULL;
  1459. int     workbench = FALSE,  /* started from Workbench? */
  1460.         taskLength = 0, pos, newPropFont, newMonoFont, wide = 0;
  1461. UBYTE   **tools;
  1462. BYTE    priority;
  1463. ULONG   class;
  1464. WORD    winLeft, winTop, winWidth, winHeight, iconLeft, iconTop, commodity, popup, confirm, iconify = FALSE,
  1465.         height, sysHeight, sysWidth, code,
  1466.         tempCommodity, tempPopup, tempConfirm, tempIconify, tempPropSize, tempMonoSize, windowTop = 0;
  1467. char    *myName = NULL,  /* to be filled in from WBStartup message */
  1468.         hotkey[MaxHotkey + 1],
  1469.         propString[MAXFONTNAME + 4], monoString[MAXFONTNAME + 4],  /* three characters for the size, plus one for the NULL at the end */
  1470.         tempPropName[MAXFONTNAME + 1], tempMonoName[MAXFONTNAME + 1];
  1471.  
  1472. struct NewBroker newBroker =
  1473.     {
  1474.     NB_VERSION,
  1475.     "PriMan",
  1476.     "PriMan v1.1 by Barry McConnell",
  1477.     "Task priority manager",
  1478.     NBU_UNIQUE | NBU_NOTIFY,
  1479.     COF_SHOW_HIDE,
  1480.     0, 0, 0
  1481.     };
  1482.  
  1483.  
  1484. osver = SysBase -> LibNode.lib_Version;  /* running under 2.0, 3.0, ...? */
  1485. port = CreateMsgPort();
  1486.  
  1487. tools = ArgArrayInit(argc, argv);
  1488.  
  1489. winLeft = (WORD)ArgInt(tools, "LEFT", 150);
  1490. winTop = (WORD)ArgInt(tools, "TOP", 50);
  1491. winWidth = (WORD)ArgInt(tools, "WIDTH", 220);
  1492. winHeight = (WORD)ArgInt(tools, "HEIGHT", 270);
  1493. propName.ta_YSize = (UWORD)ArgInt(tools, "GADSIZE", 0);
  1494. monoName.ta_YSize = (UWORD)ArgInt(tools, "LISTSIZE", 0);
  1495. iconLeft = (WORD)ArgInt(tools, "ICONLEFT", 0);
  1496. iconTop = (WORD)ArgInt(tools, "ICONTOP", 0);
  1497. priority = (BYTE)ArgInt(tools, "CX_PRIORITY", 0);
  1498.  
  1499. strcpy(propName.ta_Name, ArgString(tools, "GADFONT", " "));
  1500. strcpy(monoName.ta_Name, ArgString(tools, "LISTFONT", " "));
  1501. strncpy(hotkey, ArgString(tools, "CX_POPKEY", "alt p"), MaxHotkey);
  1502.  
  1503. confirm = (ArgString(tools, "CONFIRM", "Y")[0] & ~32) != 'N';
  1504. commodity = (ArgString(tools, "COMMODITY", "Y")[0] & ~32) !='N';
  1505. popup = (ArgString(tools, "CX_POPUP", "Y")[0] & ~32) != 'N';
  1506.  
  1507. if (!argc)  /* started from Workbench? */
  1508.     {
  1509.     myName = ((struct WBStartup *)argv) -> sm_ArgList -> wa_Name;
  1510.     if (myIcon = GetDiskObject(myName));  /* read in .info file */
  1511.         {
  1512.         wbIcon = GetDefDiskObject(WBTOOL);
  1513.         wbIcon -> do_Gadget.Flags = myIcon -> do_Gadget.Flags;
  1514.         wbIcon -> do_Gadget.Width = myIcon -> do_Gadget.Width;
  1515.         wbIcon -> do_Gadget.Height = myIcon -> do_Gadget.Height;
  1516.         wbIcon -> do_CurrentX = iconLeft;
  1517.         wbIcon -> do_CurrentY = iconTop;
  1518.         wbIcon -> do_Gadget.GadgetRender = myIcon -> do_Gadget.GadgetRender;
  1519.         wbIcon -> do_Gadget.SelectRender = myIcon -> do_Gadget.SelectRender;
  1520.         wbIcon -> do_Type = NULL;
  1521.         workbench = TRUE;
  1522.         iconify = (ArgString(tools, "ICONIFY", "N")[0] & ~32) == 'Y';
  1523.         }
  1524.     }
  1525.  
  1526. newBroker.nb_Port = port;
  1527. newBroker.nb_Pri = priority;
  1528.  
  1529. if (commodity)
  1530.     setupCommodity(hotkey, port, mainWindow, setWindow, &newBroker, &broker, &filter, &sender, &translate);
  1531.  
  1532. if (!error)
  1533.     error = !popup && (iconify || commodity) ? CLOSE_MAIN : OPEN_MAIN;
  1534.     
  1535. propFontReq = AllocAslRequest(ASL_FontRequest, NULL);
  1536. monoFontReq = AllocAslRequest(ASL_FontRequest, NULL);
  1537.  
  1538. while (error < 100)  /* i.e. no _real_ error */
  1539.     {
  1540.     if (!error)  /* nothing left to process? */
  1541.         {
  1542.         window = NULL;  /* assume it's not from GadTools */
  1543.         WaitPort(port);
  1544.         if (message = GetMsg(port))
  1545.             {
  1546.             if (((struct AppMessage *)message) -> am_Type == MTYPE_APPICON && ((struct AppMessage *)message) -> am_ID == 42)  /* user clicked on AppIcon? */
  1547.                 error = OPEN_MAIN;
  1548.             else
  1549.                 switch (class = CxMsgType((CxMsg *)message))
  1550.                     {
  1551.                     case CXM_COMMAND:
  1552.                         switch (CxMsgID((CxMsg *)message))
  1553.                             {
  1554.                             case CXCMD_APPEAR:
  1555.                             case CXCMD_UNIQUE:
  1556.                                 error = OPEN_MAIN;
  1557.                                 break;
  1558.  
  1559.                             case CXCMD_DISAPPEAR:
  1560.                                 error = CLOSE_MAIN;
  1561.                                 break;
  1562.  
  1563.                             case CXCMD_KILL:
  1564.                                 error = QUIT;
  1565.                                 break;
  1566.                             }
  1567.                         break;
  1568.  
  1569.                     case CXM_IEVENT:  /* user pressed hotkey */
  1570.                         error = OPEN_MAIN;
  1571.                         break;
  1572.  
  1573.                     default:  /* must have been from GadTools */
  1574.                         if (imsg = GT_FilterIMsg((struct IntuiMessage *)message))
  1575.                             {
  1576.                             class = imsg -> Class;
  1577.                             selectedGad = imsg -> IAddress;
  1578.                             code = imsg -> Code;
  1579.                             window = imsg -> IDCMPWindow;
  1580.                             GT_PostFilterIMsg(imsg);
  1581.                             }
  1582.                         break;
  1583.                     }
  1584.  
  1585.             ReplyMsg(message);
  1586.  
  1587.             if (window && class != IDCMP_INTUITICKS)  /* we get this often and don't want to waste time on it */
  1588.                 {
  1589.                 if (window == mainWindow)
  1590.                     handleMainWindow(class, code, selectedGad, mainWindow, setWindow, mainGads,
  1591.                                         &winLeft, &winTop, &winWidth, &winHeight, 
  1592.                                         listGad, sliderGad, breakGad, killGad,
  1593.                                         &pos, &wide, confirm,
  1594.                                         ¤t, &taskList, taskLength);
  1595.                 else if (window == setWindow)
  1596.                     {
  1597.                     handleSettingsWindow(class, code, port, selectedGad, mainWindow, setWindow,
  1598.                                             &tempPropSize, &tempMonoSize, &confirm, &tempConfirm,
  1599.                                             &iconify, &tempIconify, iconLeft, iconTop,
  1600.                                             &commodity, &tempCommodity, &popup, &tempPopup, hotkey, &priority,
  1601.                                             propFontReq, monoFontReq, propFontGad, monoFontGad,
  1602.                                             popupGad, hotkeyGad, priorityGad, &propName, &monoName, 
  1603.                                             propString, monoString, tempPropName, tempMonoName,
  1604.                                             myName, windowTop, &newPropFont, &newMonoFont,
  1605.                                             &newBroker, &broker, &filter, &sender, &translate);
  1606.                     if (error >= 100)  /* abort immediately */
  1607.                         {
  1608.                         FreeWindow(&mainWindow, mainGads);
  1609.                         FreeWindow(&setWindow, setGads);
  1610.                         FreeRemember(&memoryKey, TRUE);
  1611.                         free(&propFont, monoFont, visInfo, myScreen);
  1612.                         }
  1613.                     }
  1614.                 }
  1615.             }
  1616.         }
  1617.  
  1618.     switch (error)
  1619.         {
  1620.         case OPEN_MAIN:
  1621.             error = 0;
  1622.  
  1623.             if (appIcon)
  1624.                 {
  1625.                 RemoveAppIcon(appIcon);
  1626.                 appIcon = NULL;
  1627.                 }
  1628.  
  1629.             if (mainWindow)
  1630.                 {
  1631.                 WindowToFront(mainWindow);
  1632.                 if (setWindow)
  1633.                     {
  1634.                     WindowToFront(setWindow);
  1635.                     ActivateWindow(setWindow);
  1636.                     }
  1637.                 else
  1638.                     ActivateWindow(mainWindow);
  1639.                 }
  1640.             else
  1641.                 {
  1642.                 setup(&propFont, &monoFont, &propName, &monoName,
  1643.                         &myScreen, &visInfo, &height, &sysWidth, &sysHeight);
  1644.                 if (!error)
  1645.                     {
  1646.                     openMainWindow(&mainWindow, myScreen, &mainGads,
  1647.                                     &listGad, &sliderGad, &breakGad, &killGad,
  1648.                                     propFont, &propName, &monoName,
  1649.                                     port, visInfo, height, sysHeight, sysWidth, &taskLength,
  1650.                                     &windowTop, winLeft, winTop, &winWidth, &winHeight);
  1651.                     if (!error)
  1652.                         error = UPDATE;
  1653.                     }
  1654.                 }
  1655.             break;
  1656.  
  1657.         case OPEN_SETTINGS:
  1658.             error = 0;
  1659.             if (setWindow)  /* already open? */
  1660.                 {
  1661.                 WindowToFront(setWindow);
  1662.                 ActivateWindow(setWindow);
  1663.                 }
  1664.             else
  1665.                 openSettingsWindow(mainWindow, &setWindow, myScreen,
  1666.                                     &setGads, &propFontGad, &monoFontGad, &confirmGad, &iconifyGad,
  1667.                                     &comGad, &popupGad, &hotkeyGad, &priorityGad,
  1668.                                     propFont, &propName, &monoName, height, sysHeight, sysWidth, workbench,
  1669.                                     &newPropFont, &newMonoFont, port, visInfo,
  1670.                                     windowTop, &tempPropSize, &tempMonoSize,
  1671.                                     confirm, &tempConfirm, iconify, &tempIconify,
  1672.                                     commodity, &tempCommodity, popup, &tempPopup, hotkey, &priority,
  1673.                                     propString, monoString, tempPropName, tempMonoName);
  1674.             break;
  1675.  
  1676.         case CLOSE_MAIN:
  1677.             if (!(iconify || commodity))
  1678.                 error = QUIT;
  1679.             else
  1680.                 {
  1681.                 error = 0;
  1682.                 GetPos(mainWindow, &winLeft, &winTop, &winWidth, &winHeight);
  1683.                 FreeWindow(&mainWindow, mainGads);
  1684.                 FreeWindow(&setWindow, setGads);
  1685.                 FreeRemember(&memoryKey, TRUE);
  1686.                 free(&propFont, monoFont, visInfo, myScreen);
  1687.                 if (iconify)
  1688.                     appIcon = AddAppIcon(42, NULL, "PriMan", port, NULL, wbIcon, TAG_END);
  1689.                 }
  1690.             break;
  1691.  
  1692.         case REDRAW_MAIN:
  1693.             error = 0;
  1694.             FreeGadgets(mainGads);
  1695.             openMainWindow(&mainWindow, myScreen, &mainGads,
  1696.                             &listGad, &sliderGad, &breakGad, &killGad,
  1697.                             propFont, &propName, &monoName,
  1698.                             port, visInfo, height, sysHeight, sysWidth, &taskLength,
  1699.                             &windowTop, winLeft, winTop, &winWidth, &winHeight);
  1700.             if (!error)
  1701.                 error = UPDATE;
  1702.             break;
  1703.  
  1704.         case UPDATE:
  1705.             error = 0;
  1706.             createList(&taskList, &memoryKey, mainWindow, taskLength,
  1707.                         listGad, sliderGad, breakGad, killGad);
  1708.             pos = -1;
  1709.             break;
  1710.  
  1711.         case CLOSE_SETTINGS:
  1712.             error = 0;
  1713.             FreeWindow(&setWindow, setGads);
  1714.             break;
  1715.  
  1716.         case NEW_FONT:
  1717.             GetPos(mainWindow, &winLeft, &winTop, &winWidth, &winHeight);
  1718.             FreeWindow(&setWindow, setGads);
  1719.             FreeWindow(&mainWindow, mainGads);
  1720.             free(&propFont, monoFont, visInfo, myScreen);
  1721.             error = OPEN_MAIN;
  1722.             break;
  1723.  
  1724.         case QUIT:
  1725.             error = ALL_OKAY;
  1726.             FreeWindow(&mainWindow, mainGads);
  1727.             FreeWindow(&setWindow, setGads);
  1728.             FreeRemember(&memoryKey, TRUE);
  1729.             free(&propFont, monoFont, visInfo, myScreen);
  1730.             break;
  1731.         }
  1732.     }
  1733.  
  1734. DeleteCxObjAll(broker);
  1735. FreeAslRequest(propFontReq);
  1736. FreeAslRequest(monoFontReq);
  1737.  
  1738. if (appIcon)
  1739.     RemoveAppIcon(appIcon);
  1740. if (wbIcon)
  1741.     FreeDiskObject(wbIcon);
  1742. if (myIcon)
  1743.     FreeDiskObject(myIcon);
  1744.  
  1745. ArgArrayDone();
  1746.  
  1747. Forbid();
  1748. while (message = GetMsg(port))  /* clean up */
  1749.     ReplyMsg(message);
  1750. DeleteMsgPort(port);
  1751. Permit();
  1752. }
  1753.  
  1754.  
  1755. /*
  1756.     Open all libraries, and display any error messages.
  1757. */
  1758.  
  1759. void main(int argc, char *argv[])
  1760. {
  1761. struct EasyStruct errorMessage =
  1762.     {
  1763.     sizeof(struct EasyStruct),
  1764.     0,
  1765.     "PriMan fatal error",
  1766.     "%s",
  1767.     "Okay"
  1768.     };
  1769.  
  1770.  
  1771. if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37))
  1772.     {
  1773.     if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))
  1774.         {
  1775.         if (GadToolsBase = OpenLibrary("gadtools.library", 37))
  1776.             {
  1777.             if (IconBase = OpenLibrary("icon.library", 37))
  1778.                 {
  1779.                 if (CxBase = OpenLibrary("commodities.library", 37))
  1780.                     {
  1781.                     handleMessages(argc, argv);
  1782.                     if (error)
  1783.                         {
  1784.                         switch (error)
  1785.                             {
  1786.                             case LOCK_ERROR:
  1787.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't lock default public screen");
  1788.                                 break;
  1789.  
  1790.                             case VISINFO_ERROR:
  1791.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't get VisualInfo for this screen");
  1792.                                 break;
  1793.  
  1794.                             case FONT_ERROR:
  1795.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't open your selected fonts");
  1796.                                 break;
  1797.  
  1798.                             case GADGET_ERROR:
  1799.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't create list of gadgets\n(Out of memory?)");
  1800.                                 break;
  1801.  
  1802.                             case MAIN_ERROR:
  1803.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't open main window\n(Out of memory?)");
  1804.                                 break;
  1805.  
  1806.                             case TASK_ERROR:
  1807.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't create list of tasks\n(Out of memory?)");
  1808.                                 break;
  1809.  
  1810.                             case SETTINGS_ERROR:
  1811.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't open settings window\n(Out of memory?)");
  1812.                                 break;
  1813.  
  1814.                             case CX_ERROR:
  1815.                                 EasyRequest(NULL, &errorMessage, NULL, "Can't set up Commodity interface\n");
  1816.                                 break;
  1817.                             }
  1818.                         }
  1819.                     CloseLibrary(CxBase);
  1820.                     }
  1821.                 CloseLibrary(IconBase);
  1822.                 }
  1823.             CloseLibrary(GadToolsBase);
  1824.             }
  1825.         CloseLibrary((struct Library *)GfxBase);
  1826.         }
  1827.     CloseLibrary((struct Library *)IntuitionBase);
  1828.     }
  1829. }
  1830.